<!DOCTYPE html>
<html>
  <head>
    <!--
      
      $RCSfile$
      $Author: hansonr $
      $Date: 2016-07-11 22:28:38 -0500 (Mon, 11 Jul 2016) $
      $Revision: 21173 $

      Copyright (C) 2005  The Jmol Development Team

      Contact: jmol-developers@lists.sf.net

      This library is free software; you can redistribute it and/or
      modify it under the terms of the GNU Lesser General Public
      License as published by the Free Software Foundation; either
      version 2.1 of the License, or (at your option) any later version.
      
      This library is distributed in the hope that it will be useful,
      but WITHOUT ANY WARRANTY; without even the implied warranty of
      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      Lesser General Public License for more details.
      
      You should have received a copy of the GNU Lesser General Public
      License along with this library; if not, write to the Free Software
      Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
      02111-1307  USA.
      
    -->
  </head>
  <body bgcolor="white">
    
<h1>Jmol SMILES, Jmol SMARTS, Jmol bioSMILES, and Jmol bioSMARTS</h1>
Robert M. Hanson<br>Department of Chemistry<br>St. Olaf College<br>8/26/2015
<br><br>
This document describes a specification for an extension of SMARTS for use in 
3D molecular atom search and selection as well as biomolecular sequence and cross-link searching. 
This specification was initially implemented in Jmol 12.0 and revised for Jmol 14.4. It is really a set of specifications:

<ul>

<li><b>Jmol SMILES</b> A minor adaptation of SMILES, allowing comments and white space, and allowing more than 99 concurrently open connections. 
</li>
<li><b>Jmol bioSMILES</b>  An extension of Jmol SMILES that incorporates both biomolecular sequence/cross-linking
information along with more standard molecular or ionic components, allowing for extensive searching of biomolecular frameworks. 
The coding basically substitutes residues for SMILES atoms 
and cross-linking and base pairing for SMILES "ring" connections. 
</li>
<li><b>Jmol SMARTS</b> An extension of SMARTS substructure searching that allows several more
features, including (among others) searching of 
molecular distance, angle, and torsion measurements, searching of both standard SMARTS substructure and Jmol bioSEQUENCE information within a 3D molecular structure, 
a standard SMILES string, Jmol SMILES string, or Jmol bioSMILES string. 
</li>
<li><b>Jmol bioSMARTS</b>An extension of Jmol SMARTS that allows additional substructure search options relevant to biomolecules.
</li>
</ul>
    The <a href=".">org.jmol.smiles</a> package provides extensive functionality for selecting
    atoms within a three-dimensional model based on SMILES and SMARTS strings. 
<br><br> Besides a presentation of general considerations, a detailed <a href="#smilesspecs">specification</a> for syntax, and 
the term <a href="#aromaticity">aromatic</a> is defined.
<br><br>


<br><br>     
 <h3>Comparision to <a target="_blank" href="http://www.daylight.com/dayhtml/doc/theory/theory.smiles.html">Daylight SMILES</a></h3>
 All single-component aspects of Daylight SMILES are implemented, including
    aromaticity and atom- and bond-based stereochemistry ("chirality").
<br><br>     
<b>aromaticity</b>
 
<ul>
<li>The default Jmol SMILES and Jmol SMARTS defines "aromatic" unambiguously and strictly geometrically. However, starting
with Jmol 12.3.24, you can use the directive /aromaticStrict/ to add to that a 6-electron Hueckel model for specifying aromaticity. 
    see <a href="#aromaticity">below</a>.

</li><li>Note that "aromatic" is not restricted to any specific subset of elements.
</li><li>For large biomolecule searches, the search for aromatic rings can be time consuming and unnecessary.
Adding the directive "/noAromatic/" at the beginning of the search pattern will turn off all checks for aromaticity
and may dramatically increase processing speed.
</li></ul>
  
Jmol SMILES adds the following two aspects to Daylight SMILES:
<br>
<br>
<table border="1" cellpadding="5" width="500">
<tr><td valign="top"><b>%(n)</b></td><td>Jmol SMILES adds unlimited branching. Daylight SMILES 
allows indication of "rings" using the digits 1-9, for example, <b>C1CCCC1</b>. Actually, these numbers
do not necessarily indicate rings. Rather, in association with "." component notation, 
they may simply indicate <em>connectivity</em>. For example, ethane can be <b>CC</b> or <b>C1.C1</b>.
The original SMILES notation allows up to 99 open connections using <b>$nn</b>, where nn is 10-99. 
In generalizing SMILES to Jmol SMILES and Jmol bioSMILES, since connections can represent hydrogen bonds between nucleic acid chains, it was necessary to allow more 
than 99 open connections. Adding parentheses, for example <b>%(130)</b>, allows for 
an unlimited number of open connections. 

Note that despite this allowance, Jmol itself will not generate 
SMILES strings using this notation unless it is absolutely necessary. 

</td></tr>
<tr><td valign="top"><b>//*...*//</b></td><td>Jmol SMILES is free-formatted, allowing
standard whitespace as well as general comments in the form //*....*// anywhere within the string. 
For example, note the difference when Jmol debugging is set ON for the <b>show SMILES</b> command:
<br><br><b>$ show SMILES</b>
<pre>
[n](C)1c2=O.c23=c4[n](C)c1=O.[n](C)3c=[n]4
</pre>
<b>$ set debug; show SMILES</b>
<pre>
//* N1 #1 *//	[n](
//* C2 #2 *//	C)1
//* C13 #13 *//	c2=
//* O14 #14 *//	O.
//* C12 #12 *//	c23=
//* C7 #7 *//	c4
//* N5 #5 *//	[n](
//* C6 #6 *//	C)
//* C3 #3 *//	c1=
//* O4 #4 *//	O.
//* N10 #10 *//	[n](
//* C11 #11 *//	C)3
//* C9 #9 *//	c=
//* N8 #8 *//	[n]4
</pre>
This allows a direct correlation between an actual atom in the 3D structure and its contribution  to the SMILES string. 
<br><br>Comments are used in Jmol bioSMILES representations for indicating
the Jmol version used for its creation as well as chain and residue information:
<br><br><b>$ load =1crn; print {*}.find("SEQUENCE")</b>
<pre>
//* Jmol bioSMILES 14.3.16_2015.08.25  2015-08-25 09:07 1 *//
//* chain A protein 1 *// ~p~TTCCPSIVARSNFNVCRLPGTPEAICATYTGCIIIPGATCPGDYAN //* 46 *//
</pre>
</td></tr>
</table>  
<br>
<br>
Jmol bioSMILES adds the following to Jmol SMILES:
<br>
<br>
<table border="1" cellpadding="5" width="500">
<tr><td valign=top>~X~</td><td>
Jmol bioSMILES separates all protein, nucleic, and carbohydrate polymers into separate SMILES components,
separated by ".". 
The <b>Jmol bioSEQUENCE type</b>, consisting of a character surrounded by two tildes,
 introduces each Jmol bioSEQUENCE component. 
The character X may be one of <em>p</em>, <em>d</em>, <em>r</em>, or <em>c</em>, 
indicating a protein, DNA, or RNA sequence, respectively. 
Generally, the string will be 
a sequence of standard single-character group symbols appropriate for that sequence type.

For example, the Jmol bioSEQUENCE
string created using the commands <b>load =1crn; print {*}.find("SEQ")</b> is:
<pre>
~p~TTCCPSIVARSNFNVCRLPGTPEAICATYTGCIIIPGATCPGDYAN
</pre>
When a group is a non-standard amino acid or is present, it is indicated by its residue name in brackets.

For example, the Jmol bioSEQUENCE returned from <b>load =4zyg; print {:A and protein}.find("SEQ")</b> 
 is: 
<pre>
 ~p~MLVYGLYKSPLGYITVAKDDKGFIMLDFCDCVEGNSRDDSSFTEFFHK
  LDLYFEGKPINLREPINLKTYPFRLSVFKEVMKIPWGKVMTYKQIADSLGTSPRAVGMALSKNPILLIIP<b>[SMC]</b>HR
  VIAENGIGGYSRGVKLKRALLELEGVKIPE
</pre>  
where <b>[SMC]</b> indicates S-methylcysteine.
<br><br>  
Components that are not bioSEQUENCE types will indicate connectivity to a bioSEQUENCE (if such connection exists)
via a fully qualified bioSMILES designation for the connected atoms. 
For example, the magnesium atom component in PDB structure 1p9b is described by: 
<pre>
[Mg]123456.O3[C]N([O])[C][C]([O])[O].[IMO.O1#8]4.[GDP.O2B#8]2.[GLY.O#8]5.[ASP.OD1#8]6.[GDP.O2A#8]1.
</pre>
(The element number, #8 here, allows searching these jmol bioSMILES strings themselves, in the absence of the associated model.) 
Notice that connection 3 here is a to an unidentified ligand. Jmol bioSMILES only abbreviates groups that are within polymers.
Unconnected components such as water molecules will not be repeated; the Jmol bioSMILES representation of 
a protein with associated water molecules will only show one component in the form:
<pre>
[O].
</pre>
</td></tr>
<tr><td valign="top">  
<b>":"</b></td><td> 
Jmol bioSEQUENCES utilize the bond type ":" to indicate "cross-linked groups". 
Recognized cross-linking includes hydrogen bonding between the purine N1 and pyrimidine N3 in nucleic acids,
hydrogen bonds created with <b>create hbonds</b>, cysteine-cysteine disulfide bonds 
in proteins, and ether linkages between carbohydrate residues.
For instance, the commands <b>load =3LL2; print {carbohydrate}.find("SEQ", true)</b> reports for this branched carbohydrate:
<pre>
~c~[MAN]:1[MAN]:2[MAN].~c~[MAN]:2[MAN].~c~[MAN]:1[MAN][MAN]
</pre>
indicating a branched manose hexamer. No indication is given for exact atom-atom connectivity in the Jmol bioSEQUENCE; all connectivity is at the level of residues.
</td></tr> 


</table>  
<br>
<br>


 <h3>Comparision to <a target="_blank" href="http://www.daylight.com/dayhtml/doc/theory/theory.smarts.html">Daylight SMARTS</a></h3>
<ul>
<li>[H1] interpreted as [*H1] -- "an atom with one connected H atom".

</li><li>Allows definition of [$XXX] variables:
<pre>
      Var x = '$R1="[CH3,NH2]";$R2="[OH]"; {a}[$R1]' // select aromatic atoms attached to CH3 or NH2  
      select within(SMARTS,@x)
</pre> 
Note that these variables are any string whatsoever, not just atom sets. The syntax is simply:
<ul><li>Each variable definition takes the form $ [name] =" [definition] " [comments] ;
</li><li>[name] must start with a letter and can contain any characters other than '$', '=', '(', and ']'.
</li><li>[definition] can be any valid SMARTS characters. 
</li><li>[comments] can be any characters other than ';'. 
</li><li>The actual pattern starts after the last variable definition.
</li><li>Nested variables are allowed, but note that this may require using the recursion syntax, $(...): 
<pre>
      Var x = '$R1="[CH3,NH2]";$R2="[$($R1),OH]"; {a}[$R1]' // select aromatic atoms attached to CH3, NH2, or OH  
      select within(SMARTS,@x)
</pre> 
</li><li>For $xxx="yyyy", all occurrances of the string "[$xxx]" are replaced within the pattern prior to parsing. 
</li></ul>
<br>

</li><li>Implements nested ("recursive") SMARTS: 
<pre> 
      Var x = '$R1="[CH3,NH2]";$R2="[OH]";  {a}[$([$R1]),$([$R2])]' // aromatic attached to CH3, NH2, or OH
      select within(SMARTS,@x)
</pre>
    Note that $(...) need not be within [...], and 
    wherever it is, it always means "just the first atom".
</li>

</li><li>All primitives that are not element names, <b>*</b>, <b>A</b>, or <b>a</b> must be 
    enclosed in brackets. In addition, the following elements must be enclosed in brackets
    because their two-letter combination Xy implies the non-aromatic element X attached 
    to the aromatic element y: Ac, Ba, Ca, Na, Pa, and Sc.
    
</li><li>Allows any order of bracketed primitives: [H2C13] same as [13CH2].
 
</li><li>All atom and bond logic implemented: [X,!X,X&X,X&X&X;X&X]-,=X
 
</li><li>"&" is optional: [13CH2] same as [13&C&H2]
    except in cases of ambiguity with element symbols: [Rh] is rhodium, not [R&h].
 
</li><li>Jmol SMARTS does NOT implement:
<ul><li> "zero-level parentheses", since the match is 
    always only within a given model (but note that you can still use "." 
    to indicate that the two search sections are not connected.
</li><li>"?" in atom stereochemistry ("chirality") because 
    3D structures are always defined stereochemically.
 
</li><li>"?" for bond stereochemistry, as 3D structures
    are always defined stereochemically
</li></ul>

</li></ul>

<b>primitives and in-line options</b>

<br><br>
All Daylight SMARTS primitives are implemented. These include:
<br>
<table border="1" cellpadding="5" width="500">
<tr><td>[Element]</td><td>capitalized - standard notation Na, Si, etc. -- specific non-aromatic atom</td></tr>
<tr><td>[element]</td><td>uncapitalized - specific aromatic atom (as for standard notation, no limitations)</td></tr>
<tr><td>*</td><td>any atom</td></tr>
<tr><td>A</td><td>any non-aromatic atom</td></tr>
<tr><td>a</td><td>any aromatic atom</td></tr>
<tr><td>#</td><td>atomic number</td></tr>
<tr><td>(integer)</td><td>mass number -- Note, however, that [H1] is [*H1], "any atom with one attached hydrogen", not unlabeled hydrogen, [1H].</td></tr>
<tr><td>D</td><td>degree - total number of connections</td></tr>
<tr><td>H</td><td>exact hydrogen count</td></tr>
<tr><td>h</td><td>"implicit" hydrogen count (atoms are not in structure)</td></tr>
<tr><td>R</td><td>in the specified number of rings</td></tr>
<tr><td>r</td><td>in ring of a given size (not restricted to SSSR set)</td></tr>
<tr><td>v</td><td>valence (total bond order)</td></tr>
<tr><td>X</td><td>calculated connectivity, including implicit hydrogens</td></tr>
<tr><td>x</td><td>number of ring bonds</td></tr>
<tr><td>@</td><td>stereochemistry</td></tr>
</table>
<br>

Jmol SMARTS adds the following primitives:
<br>
<br>
<table border="1" cellpadding="5" width="800">
<tr><td>d</td><td>non-hydrogen degree -- number of non-hydrogen connections</td></tr>
<tr><td>=</td><td>Jmol atom index, for example: [=23]</td></tr>
<tr><td>"xxx"</td><td>atom type, in double quotes, for example: ["39"r5] (After <b>calculate partialcharge</b> this will be the MMFF94 atom type. [Jmol 12.3.24]</td></tr>
<tr><td>$(select xxx)"</td><td>external selection method. For Jmol, this is an atom expression. For example: [c$(select temperature>10)] [Jmol 12.3.26]</td></tr>
<tr><td>r500</td><td>a specifically aromatic 5-membered ring [Jmol 12.3.24]</td></tr>
<tr><td>r600</td><td>a specifically aromatic 6-membered ring [Jmol 12.3.24]</td></tr>
<tr><td>number?</td><td>mass number or undefined (so, for example, [C12?] means any carbon that isn't explicitly C13 or C14</td></tr>
<tr><td>$n(pattern)</td><td>A specific number of occurances of <b>pattern</b>. For example, <b>C[$3(C=C)]C</b> is synonymous with <b>CC=CC=CC=CC</b>.</td></tr>
<tr><td>$min-max(pattern)</td><td>A variable number of occurances of <b>pattern</b>. 
For example: <b>A[$0-2(C:G)]A</b> is synonymous with <b>AA</b> or <b>AC(:G)A</b> or <b>AC(:G)C(:G)A</b>.</td></tr>
<tr><td>residueName#resno^insCode.atomName#atomicNumber</b> </td><td>
All five fields are optional; only the period itself is required.
This primitive may appear with other primitives provided (a) it is first, and (b) it is followed by an operator ("," ,"&", or ";").
This allows searching a bioSMILES string using SMARTS patterns that only involve standard atom types. In the above example, 
notice that the connecting atoms to protein chains within the non-bioSEQUENCE component indicates the
connections to the protein using this extended notation. Thus, both the actual 3D model and the bioSMARTS string for 1d66
can be searched using the SMARTS search "[Cd][S]" as well as the more specific search "Cd[*.SG]". 
Wild cards provide additional options: [*#35.], [ALA.*], [*#*^A.] [*.*], [*.CA]; however, their presence is optional: [#35.], [ALA.], [^A.] [.], [.CA]. 
The special designation "0" for an atom name, as in <b>[GLY.0]</b>, indicates the "lead atom" -- the alpha carbon for proteins,
the phosphorus atom in nucleic acids, or the anomeric carbon in carbohydrates.    
</td></tr>


</table>  
<br>
<br>
Jmol SMARTS adds the following in-line options:
<br>
<br>
<table border="1" cellpadding="5" width="500">
<tr><td valign=top>
/..../</td><td>
<b>processing directives</b> Jmol recognizes <b>/..../</b> at the beginning of a pattern as processing directives.
These directives can be introduced individually or as groups. They are not case-sensitive. 
<b>/noaromatic/ /nostereo/</b> is read the same as  <b>/noAromatic,noStereo/</b>.   
<ul><li>
<b>invertStereo</b> reverses the sense of chirality (R-, S- stereochemistry). Double-bond stereochemistry is not reverse.  
<b>noStereo</b> turns off all stereochemical checking.  
</li><li><b>aromaticDouble</b> allows for using "=" between two aromatic atoms to indicate an explicitly double aromatic bond.
To specify an explicitly single aromatic bond, use <b>@&!=</b>. 
<b>aromaticStrict</b> uses a 6-electron Hueckel model for specifying aromaticity.
</li><li><b>noAromatic</b> turns off all aromaticity checks.It may be desirable when no distinction between
aromatic and nonaromatic atoms is desired. For large biomolecules /noAromatic/ can 
dramatically improve processing speed when no check for aromaticity is necessary. 
All atoms are then considered NOT aromatic.
</li></ul>
</td></tr>
<tr><td>{...}</td>
<td>

<br><br>
<b>Jmol atom selection</b>

Then general way within Jmol to select atoms based on SMARTS searches is to use <b>select search("...")</b>. 
To assign variables to the results of a search, one can use the find() command.

However, to select one or more atoms within the found pattern, simply enclose the desired atoms in { }: 
 <b>select search("{C}C=O")</b>, for example, returns all alpha carbons, 
 and <b>select search("~d~G{C}A")</b> returns all DNA cytidines that are in GCA sequences.

<br><br>No valence calculation is done to add any additional hydrogens to unbracketed 
atoms. "CCC" is the same as "[C][C][C]". only unbracketed or bracketed hydrogen atoms such as H[C]C or [H] 
or [2H] are selected; connected hydrogen atoms as in [CH3] are not selected.

</td></tr>


<tr><td valign="top">(.measure)</td><td>The extension capitalizes on the fact that in a standard SMARTS string, period "." cannot
ever appear immediately following an open parenthesis "(". Using this fact, the format involves the following:
<pre>
  "(." [single character type - "d" (distance), "a" (angle), or "t" (torsion)] 
         [optional numeric identifier] ":" [optional "!" (not)] [ranges] ")" 
</pre>
where      
       [ranges] is one or more ranges in the form  <b>[minimum value], [maximum value]</b> separated by commas.
That is, one or more 
This extension must appear immediately following an element symbol or a bracketed atom expression.  
The separators "," or "-" between minimum and maximum values are equivalent.
For example, the following will find all aliphatic carbon-carbon bonds that are between 1.5 and 1.6 angstroms long. 
<pre>
select search("C(.d:1.5-1.6)C")
</pre>
The following will select for all 1,2-trans-diaxial methyl groups on a cyclohexane ring, finding all torsions that are outside
the range -160 to 160 degrees:
<pre>
select search("{[CH3]}(.t:!-160,160)CC{[CH3]}")
</pre>
The following will select for all 1,2-trans-diequatorial methyl groups on a cyclohexane ring
by selecting for all adjacent methyl groups that are anit to a ring atom: 
<pre>
select search("{[$([CH3](.t:!-160,160)CC[Cr6])]}CC{[$([CH3](.t:!-160,160)CC[Cr6])]}")
</pre>
The following will select for all gauche-dimethyl groups on a cyclohexane ring:
<pre>
select search("{[CH3]}(.t:50,70,-50,-70)CC{[CH3]}")
</pre>
and the following prints the number of gauche interactions.
Division by two is necessary in this case because of the symmetry involved.
<pre>
print compare({*},{*},"MAP","[CH3](.t:50,70,-70,-50)CC[CH3]").length/2
</pre>

The default in terms of specifying which atoms are involved is simply "the next N-1 atoms," where N is 2, 3, or 4. 
For more complicated patterns, one can designate the specific atoms in the measurement using a numeric 
identifier after the measurement type. The following will
target the bond angle across the carbonyl group in the backbone of a peptide:
<pre>
select search("[*.CA](.a1:105-110)C(.a1)(=O)N(.a1)")
</pre> 
Designations can overlap; one simply adds whatever (.xn) designation is wanted after the desired atoms:
<pre>
select search("C(.a1:105,108)C(.a1)(.a2:110,130)C(.a1)(.a2)C(.a2)")
</pre> 
In Jmol, this capability is extended to the <b>measure</b> command for easy access to SMARTS-based measurements:
<pre>
select *
measure search("C(.a1:110,130)C(.a1)(=O)C(.a1)")
</pre> 
Note that the atoms in no way have to be connected. The only restriction is that the three markers for an angle
or the four markers for a torsion will be identified in order from left to right within the SMARTS string. The following,
for example, will find all carbonyl oxygen atoms that are within 5 angstroms of each other:
<pre>
select search("{O}(.d1:0,5)=C.{O}(.d1)=C")
</pre>
The "." here indicating "not bonded." {O} specifies that although we want to find the entire set, we only
want to <i>select</i> the oxygen atoms. The close of the selection brace may appear before or after the (.x) designation.
</td></tr>
<tr><td>pattern1 || pattern2</td><td> "||" indicates "or" and allows searching for multiple patterns, which may overlap.
For example: <b>select search("c{O} || c{C}")</b>. Note that the "||" syntax is an alternative to using "[,]", 
in this case being equivalent to (and slightly slower than) <b>select search("c{[O,C]}")</b>.</td></tr>
</table>  
<br>
<br>
Jmol bioSMARTS adds the following pattern options to Jmol SMARTS:
<br>
<br>
<table border="1" cellpadding="5" width="500">
<tr><td>
<b>"~"</b> 
</td><td>Any biopolymer.
</td></tr>
<tr><td>
<b>"~n~"</b> 
</td><td>DNA or RNA
</td></tr>
<tr><td valign="top">
<b>"+"</b> 
</td><td>
Jmol bioSMARTS adds the "+" bond type to indicate standard sequence. The Jmol bioSMARTS 
pattern "~p~C+C+C" is the same as "~p~CCC". In conjunction with the cross-linking 
type ":", one can do searches for double-stranded nucleic acids quite easily. 
<b>~d~CCC:GGG</b> would be three CG base-pairs (because the two strands are going in opposite direction). 
Note that Jmol atom selection can be specified by For example,  <b>select search("[CYS.CA][PRO.CB]")</b> 
would select just the alpha carbon of cysteine and the beta carbon of an adjacent proline.


</td></tr>
<tr><td valign=top>branching</td><td>Branching (cross-linking) can also be indicated using the standard 
SMILES (...) notation. So, for example, <b>~d~C(G)C(G)C(G)</b> indicates three CG base pairs.
Ring notation can also be used: <b>C:1CC(GGG:1)</b> is the same three CG base pairs.  

<br><br>An empty branch, <b>~C()</b>, indicates "not cross-linked" -- in this case 
a cysteine without a disulphide bond or a cytidine that is not base-paired. 


</td></tr>




</table>  
<br>


<b>implicit hydrogen count</b>

<ul><li>

The primitives <b>h</b> (implicit hydrogen count) and <b>X</b> (total connections, including implicit hydrogens)
require analysis of bonding around a model atom to determine the number of missing ("implicit") hydrogen atoms based on a "target valence." 
Models that specify only "aromatic" or "partial" bonding may produce ambiguous results, and for that reason, 
primitives <b>X</b> and <b>h</b> are not recommended for use. Other primitives, such as <b>D</b>, <b>d</b>, and <b>v</b> should be more useful.
The analysis Jmol uses here is the same as for how Jmol calculates the number of hydrogens to add for the <b>calculate hydrogens</b> command and 
includes:
 <ol style="list-style-type: lower-alpha;"><li>Assign the target valence <b>TV</b> as follows:
  <ul><li>For C and Si, <b>TV</b> = 4.
  </li><li>For B, N, and P, <b>TV</b> = 3.
  </li><li>For O and S, <b>TV</b> = 2.
  </li><li>For F, Cl, Br, and I, <b>TV</b> = 1.
  </li><li>For all other atoms, <b>TV</b> = 0.
  </li></ul>
 </li><li>Obtain the formal charge on the atom, <b>C</b>.
 </li><li>Group IV elements such as carbon are unique, in that their cations are valence-poor, not valence-rich. 
 So for carbon and silicon, subtract the ABSOLUTE VALUE of <b>C</b> from the target valence.
 In all other cases, let <b>TV</b> = <b>TV</b> + <b>C</b>.
 </li><li>Determine the overall valence of the atom, <b>OV</b>. This is calculated by adding up all the bond orders to the atom.
 </li><li>Subtract <b>OV</b> from <b>TV</b> to get the number of implicit hydrogen atoms. If this number is less than zero, assign zero.
 </ol>
</li><li>Thus, the implicit hydrogen count is:
 <ul><li> 0 for all atoms other than {B,C,N,O,P,Si,S}
  </li><li>0 for BR3
  </li><li>0 for CR4, 1 for CR3, 2 for CR2, 3 for CR
  </li><li>0 for CR3(+), 0 for CR3(-)
  </li><li>0 for R=CR2, 1 for R=CR, 2 for R=C, 1 for C#R (triple bond)
  </li><li>0 for NR3, 1 for NR2, 2 for NR
  </li><li>0 for RN=R, 1 for R=N
  </li><li>1 for NR3(+), 1 for R=NR(+), 1 for RN(-)
  </li><li>0 for OR2, 0 for O=R, 1 for OR
  </li><li>0 for RO(-), 2 for RO(+)
  </li></ul>
</li></ul>  
  

<br><br>     
<a name="smilesspecs"><h3>Detailed Jmol SMILES/bioSMILES Specification</h3></a>
<br><br>
<pre> 
      # note: prior to parsing, all white space is removed
       
   [smilesDef] == [preface] [smiles]
   [preface] == { [directiveDefs] | NULL } 
   [directiveDefs] == { [directiveDef] || [directiveDef] [directiveDefs] }
   [directiveDef] == "/" [processingDirectives] "/"
   [processingDirectives] == { [processingFlag] | [processingDirective] [processingDirectives] }
   [processingFlag] == { "noAromatic" | "aromaticDefined" | "aromaticStrict" | "noStereo" | "invertStereo"} (case-insensitive)
      # note: the noAromatic directive indicates to not distinguish between
      #       aromatic/aliphatic searches -- "C" and "c"
      # note: the noStereo directive turns off all stereochemical testing
      # note: thus, both "/noAromatic//noStereo/" and "/noAromatic noStereo/" are valid 
   [smiles] == { [entity] | [entity] "." [entity] }
   [entity] == { [bioSequence] | [molecularSequence] }
   [molecularSequence] = [node][connections] 
   [node] == { [atomExpression] | [connectionPointer] }

   [atomExpression] = { [unbracketedAtomType] 
                             | "[" [bracketedExpression] "]" }
   
   [unbracketedAtomType] == [atomType] 
                                 & ! { "Ac" | "Ba" | "Ca" | "Na" | "Pa" | "Sc"
                                     | "ac" | "ba" | "ca" | "na" | "pa" | "sc" }
      # note: Brackets are required for these elements: [Na], [Ca], etc.
      #       These elements Xy are instead interpreted as "X" "y", a single-letter
      #       element followed by an aromatic atom. 
      
   [atomType] == { [validElementSymbol] | [aromaticType] }
   [validElementSymbol] == (see <a href="../util/Elements.java">Elements.java</a>; 
                            including Xx and only through element 109)
   [aromaticType] == { [validElementSymbol].toLowerCase() }
       
   [bracketedExpression] == { "[" [atomPrimitives] "]" } 
   
   [atomPrimitives] == { [atom] | [atom] [atomModifiers] }
   [atom] == { [isotope] [atomType] | [atomType] } 
   [isotope] == [digits]
       # note -- isotope mass must come before the element symbol. 
   [digits] == { [digit] | [digit] [digits] }
   [digit] == { "0" | "1" | "2" | "3" | "4" | "5" | "6" | 7" | "8" | "9" }
   [atomModifiers] == { [atomModifier] | [atomModifier] [atomModifiers] }
   [atomModifier] == { [charge] | [stereochemistry] | [H_Prop] }
   [charge] == { "-" [digits] | "+" [digits] | [plusSet] | [minusSet] }
   [plusSet] == { "+" | "+" [plusSet] }
   [minusSet] == { "-" | "-" [minusSet] }
   [stereochemistry] == { "@"           # anticlockwise
                              | "@@"    # clockwise
                              | "@" [stereochemistryDescriptor] 
                              | "@@" [stereochemistryDescriptor] }
   [stereochemistryDescriptor] == [stereoClass] [stereoOrder]
   [stereoClass] == { "AL" | "TH" | "SP" | "TP" | "OH" }
   [stereoOrder] == [digits]
   
   [connectionPointer] == { "%" [digit][digit] | [digit] | "%(" [digits] ")"}
      # note: all connectionPointers must have a second matching connectionPointer 
      #       and must be preceded by an atomExpression for the 
      #       first occurance and either an atomExpression or a bond
      #       for the second occurance
      # note: Jmol bioSMARTS extends the possible number of rings to > 100 by 
      #       allowing %(n)

   [connections] == [connection] | NULL }
   [connection] == { [branch] | [bond] [node] } [connections]
   [branch] == { "(" { [smiles] | [bond] [smiles] } ")" | "()" }
      # note: empty parentheses "()" are ignored in SMILES and bioSMILES
   [bond] == { "-" | "=" | "#" | "." | "/" | "\\" | ":" | NULL
      # note: Jmol will not match two totally independent molecular pieces. For example,
      #       Jmol will not math [Na+].[Cl-]. However, "." can be used to clarify a
      #       structure that has "ring" bond notation:
      #       CC1CCC.C1CC   is a valid structure.
      # note: bioSEQUENCE uses ":" to indicate "cross-linked", which is the default for branches

   [bioSequence] == [bioCode] [bioNode] [connections]
   [bioCode] == { "~" | "~" [bioType] "~" }
      # note: The "~" must be the first character in a component and must be repeated 
      #       for each component (separated by ".")
   [bioType] == { "p" | "n" | "r" | "d" }
      # note: protein, nucleic, RNA, DNA
   [bioNode] == { "[" [bioResidueName] "." [bioAtomName] "]" 
                 | "[" [bioResidueName] "." [bioAtomName] "#" [atomicNumber] "]" 
                 | [bioResidueCode] } 
   [atomicNumber] == [digits]
   [bioResidueName] == { "ARG" | "GLY" ... } (case-insensitive) 
   [bioAtomName] == {"C" | "CA" | "N" ... } (case-insensitive)
   [bioResidueCode] == { "A" | "R" | "G" ... } (case-sensitive)
      # note: In a BioSEQUENCE, residues are designated using standard 1-letter-code group names
      #       or bracketed residues [xxx] with optional atoms specified: [ARG], [CYS.SG]. 
</pre>
<br><br>

<a name="specs"><h3>Detailed Jmol SMARTS/Jmol bioSMARTS Specification</h3></a>
<br><br>
<pre> 

 ######## GENERAL ########

      # note: prior to parsing, all white space is removed

   [smartDef] == [preface] [smartsSet]
   [preface] == { [directiveDefs] [variableDefs] | [variableDefs] | NULL } 
   [directiveDefs] == { [directiveDef] || [directiveDef] [directiveDefs] }
   [directiveDef] == "/" [processingDirectives] "/"
   [processingDirectives] == { [processingDirective] | [processingDirective] [processingDirectives] }
   [processingFlag] == { "noAromatic" | "aromaticDefined" | "aromaticStrict" | "noStereo" | "invertStereo"} (case-insensitive)
      # note: the noAromatic directive indicates to not distinguish between
      #       aromatic/aliphatic searches -- "C" and "c"
      # note: the noStereo directive turns off all stereochemical testing
      # note: thus, both "/noAromatic//noStereo/" and "/noAromatic noStereo/" are valid 
   [variableDefs] == [variableDef] | [variableDef] [variableDefs]
   [variableDef] ==  "$" [label] "=" "\"" [smarts] "\"" [comments] ";"
   [label] == 'A-Z' [any characters other than "=", "(", or "$"]
   [comments] == [any characters other than ";"]
      # note: Variable definitions must be parsed first. 
      #       After that, all variable references [$XXXX] are replaced
      
   [smartsSet] == { [smarts] | [smarts] "||" [smartsSet] }
      # note: Jmol adds the "or" operation "||", for example: "C=O || C=N"
      #       which, in this case, could also be written as "C=[O,N]"
      #       Jmol preprocesses these sets, evaluates them independently, and then
      #       combines them.
      
   [smarts] == { [node3D] [connections] | [bioSequence] } 
   [connections] == [connection] | NULL }
   [connection] == { [branch] | [bondExpression] [node3D] } [connections]
   [branch] == { "(" { [smarts] | [bondExpression] [smarts] } ")" | "()" }
      # note: Default bonding for a branch is single for SMARTS or cross-linked (:) for bioSEQUENCE
      # note: "()" is ignored in SMARTS and indicates "not cross-linked" in bioSEQUENCE
   
 ######## ATOMS ########
    
   [node3D] == { [atomExpression] | [atomExpression] "(." [measure] ")" | [connectionPointer] }
   [atomExpression] = { [unbracketedAtomType]
                             | [bracketedExpression] 
                             | [multipleExpression]
                             | [nestedExpression] }
   
   
   [unbracketedAtomType] == [atomType] 
                                 & ! { "Ac" | "Ba" | "Ca" | "Na" | "Pa" | "Sc"
                                     | "ac" | "ba" | "ca" | "na" | "pa" | "sc" }
      # note: Brackets are required for these elements: [Na], [Ca], etc.
      #       These elements Xy are instead interpreted as "X" "y", a single-letter
      #       element followed by an aromatic atom. 
      # note: in a bioSEQUENCE, all atom types are 1-letter code group names
      
   [atomType] == { [validElementSymbol] | "A" | [aromaticType] | "*" }
   [validElementSymbol] == (see <a href="../util/Elements.java">Elements.java</a>; 
                            including Xx and only through element 109)
   [aromaticType] == { "a" | [validElementSymbol].toLowerCase() }
       
   [bracketedExpression] == "[" { [atomOrSet] | [atomOrSet] ";" [atomAndSet] } "]" 
   
   [atomOrSet] == { [atomAndSet] | [atomAndSet] "," [atomAndSet] }
   [atomAndSet] == { [atomPrimitives] | [atomPrimitives] "&" [atomAndSet]
                              | "!" [atomPrimitive] 
                              | "!" [atomPrimitive] "&" [atomAndSet] }
                              
 ######## ATOM PRIMITIVES ########

   [atomPrimitives] == { [atomPrimitive] | [atomPrimitive] [atomPrimitives] }
       # note -- if & is not used, certain combinations of primitiveDescritors
       #         are not allowed. Specifically, combinations that together
       #         form the symbol for an element will be read as the element (Ar, Rh, etc.)
       #         when NOT followed by a digit and no element has already been defined 
       #         So, for example, [Ar] is argon, [Ar3] is [A&r3], [ORh] is [O&R&h],  
       #         but [Ard2] is [Ar&d2] -- "argon with two non-hydrogen connections"
       #         Also, "!" may not be use with implied "&". 
       #         Thus, [!a], [!a&!h2], and [h2&!a] are all valid, but [!ah2] is invalid.             
   [atomPrimitive] == { [isotope] | [atomType] | [charge] | [stereochemistry]
                              | [a_Prop] | [A_Prop] | [D_Prop] | [H_Prop] | [h_Prop] 
                              | [R_Prop] | [r_Prop] | [v_Prop] | [X_Prop]
                              | [x_Prop] | [at_Prop] | [nestedExpression] }
   [isotope] == [digits] | [digits] "?"
       # note -- isotope mass may come before or after element symbol, 
       #         EXCEPT "H1" which must be parsed as "an atom with a single H" 
   [digits] == { [digit] | [digit] [digits] }
   [digit] == { "0" | "1" | "2" | "3" | "4" | "5" | "6" | 7" | "8" | "9" }
   [charge] == { "-" [digits] | "+" [digits] | [plusSet] | [minusSet] }
   [plusSet] == { "+" | "+" [plusSet] }
   [minusSet] == { "-" | "-" [minusSet] }
   [stereochemistry] == { "@"           # anticlockwise
                              | "@@"    # clockwise
                              | "@" [stereochemistryDescriptor] 
                              | "@@" [stereochemistryDescriptor] }
   [stereochemistryDescriptor] == [stereoClass] [stereoOrder]
   [stereoClass] == { "AL" | "TH" | "SP" | "TP" | "OH" }
   [stereoOrder] == [digits]
       # note -- "?" here (unspecified) is not relevant in Jmol SMARTS, only Jmol bioSMARTS 
   
   [A_Prop] == "#" [digits]           # elemental atomic number
   [a_Prop] == "=" [digits]           # Jmol atom index (starts with 0)
   [D_Prop] == { "D" [digits] | "D" } # degree -- total number of connections 
                                      #   excludes implicit H atoms; default 1
   [d_Prop] == { "d" [digits] | "d" } # degree -- non-hydrogen connections
                                      #   default 1 
   [H_Prop] == { "H" [digits] | "H" } # exact hydrogen count 
                                      #   excludes implicit H atoms
   [h_Prop] == { "h" [digits] | "h" } # implicit hydrogens -- "h" indicates "at least one"
                                      #   (see note below)
   [R_Prop] == { "R" [digits] | "R" } # ring membership; e.g. "R2" indicates "in two rings"
                                      #   "R" indicates "in a ring" 
                                      #   !R" or "R0" indicates "not in any ring"
   [r_Prop] == { "r" [digits] | "r" } # in ring of size [digits]; "r" indicates "in a ring"
                                      #   r500 and r600 match specifically <i>aromatic</i> 
                                      #   5- and 6-membered rings, respectively [Jmol 12.3.24]
   [v_Prop] == { "v" [digits] | "v" } # valence -- total bond order (counting double as 2, e.g.)
   [X_Prop] == { "X" [digits] | "X" } # connectivity -- total number of connections
                                      #   includes implicit H atoms
   [x_Prop] == { "x" [digits] | "x" } # ring connectivity -- total ring connections
   [at_Prop] == { "\"" [charsExceptDoubleQuote] | "\"" } # atom type (in double quotes) [ Jmol 12.3.24]
   
 ######## Nested and Multiple Expressions ########
 
   [nestedExpression] == "$(" [atomExpression] ")" | "$(select" [contextualSearchPhrase] ")" 
      # note: nestedExpressions return only the first atom as a match when an atom expression 
      #       is involved, not all atoms in the expression.
      
   [contextualSearchPhrase] == [any characters with well-matched "(" and ")"]
      # note: the contextual search phrase is to be processed by the context implementing
      #       the SMARTS. In the case of Jmol, [contextualSearchPhrase] is any Jmol
      #       atom expression that can be in a standard Jmol SELECT command. 

   [multipleExpression] == { "[$" [nTimes] "(" [orExpression] ")]" 
                             | "[$[nMinimum] "-" [nMaximum](" [orExpression] ")]" }  
   [orExpression] = { [atomExpression] 
                       | [atomExpression "|" [orExpression] 
                       | [atomExpression "||" [orExpression] }
      # note: "|" and "||" are synonymous in this inner context; "|" is preferred simply
      #       for readability (whereas "||" is required for the [smartsSet] context). 
      # note: This syntax is carefully written to exclude $(xxx) by itself, which
      #       is a nestedExpression, not a multipleExpression. The difference is that
      #       the nestedExpression only returns the first atom, while the multipleExpression
      #       returns all atoms. To return only the first atom within this context 
      #       it is necessary to use a nested expression within the multiple expression.
      #       For example: "CC[$2( $(C=O) | $(C=N) )]"
      #       is the same as "CC$(C=[O,N])$(C=[O,N])", although Jmol preprocesses it as
      #          "CC$(C=O)$(C=O)||CC$(C=O)$(C=N)||CC$(C=N)$(C=O)||CC$(C=N)$(C=N)"
      
   [nTimes] == [digits]
   [nMinimum] == [digits]
   [nMaximum] == [digits]
      # note: multipleExpressions allow for searching a given number of expressions or 
      #       a variable number of expressions (including 0, perhaps)
      #       Jmol pre-processes these expressions and turns them into a set:
      #       pattern1 || pattern2 || pattern3....

 ######## BioSEQUENCE ########

   [bioSequence] == [bioCode] [bioNode] [connections]
   [bioCode] == { "~" | "~" [bioType] "~" }
      # note: The "~" must be the first character in a component and must be repeated 
      #       for each component (separated by ".")
   [bioType] == { "p" | "n" | "r" | "d" }
      # note: protein, nucleic, RNA, DNA
   [bioNode] == { "[" [bioResidueName] "]" 
                 | "[" [bioResidueName] "." [bioAtomName] "]" 
                 | "[" [bioResidueName] "." [bioAtomName] [A_Prop] "]" 
                 | [bioResidueCode] } 
   [bioResidueName] == { "*" | "ARG" | "GLY" ... } (case-insensitive) 
   [bioAtomName] == { "*" | "0" | "C" | "CA" | "N" ... } (case-insensitive)
      # note: "0" indicates the "lead atom":
      #   nucleic: P if present, or H5T if present, or O5'/O5*
      #   protein: CA
      #   carbohydrate: the first atom of the group listed in the model file
   [bioResidueCode] == { "*" | "A" | "R" | "G" ... } (case-sensitive)
      # note: wildcard or standard group 1-letter-code
      #       or, in the case of RNA or DNA:
      #         "N" (any residue; same as "*"), 
      #         "R" (any purine -- A or G)
      #         "Y" (any pyrimidine -- C or T or U)

 ######## CONNECTIONS (aka "rings") ########

   [connectionPointer] == { [digit] | "%" [digit][digit] | "%(" [digits] ")" }
      # note: All connectionPointers must have a second matching connectionPointer 
      #       and must be preceded by an atomExpression for the 
      #       first occurance and either an atomExpression or a bondExpression
      #       for the second occurance. The matching connectionPointers may be
      #       in different "components" (separated by "."), in which case they
      #       represent general connections and not necessarily rings.

 ######## BONDS ########

   [bondExpression] == { [bondOrSet] | [bondOrSet] ";" [bondAndSet] } 
   
   [bondOrSet] == { [bondAndSet] | [bondAndSet] "," [bondAndSet] }
   [bondAndSet] == { [bondPrimitives] | [bondPrimitives] "&" [bondAndSet]
                              | "!" [bondPrimitive] 
                              | "!" [bondPrimitive] "&" [bondAndSet] }
                                              
 ######## BOND PRIMITIVES ########
                              
   [bondPrimitives] == { [bondPrimitive] | [bondPrimitive] [bondPrimitives] }       
   [bond] == { "-" | "=" | "#" | "." | "/" | "\\" | ":" | "~" | "@" | "+" | "^" | NULL
      # note: All bondExpressions are not valid. Stereochemistry should not 
      #       be mixed with the others, as it represents a single bond always.
      #       In addition, "." ("no bond") cannot be mixed with any bond type.
      #       Nothing would be retrieved by "-&=", as a bond cannot be both single
      #       and double. However, "-@" is potentially very useful -- "ring single-bonds"
      #       or "=&!@" -- "doubly-bonded atoms where the double bond is not in a ring"
      # note: Jmol will not match two totally independent molecular pieces. For example,
      #       Jmol will not math [Na+].[Cl-]
      # note: "+" indicates "adjacent biomolecular groups in a chain"
      # note: a bioSEQUENCE ends with "." or the end of the string. A new bioSEQUENCE
      #       can continue with "~" immediately following this "." 
      # note: For a SMARTS search, "." indicates the start of a new subset, not necessarily a
      #       new component.
      # note: "^" indicates atropisomer bond with positive dihedral angle
      
 ######## MEASURES ########
   
   [measure] == { [measureId] | [measureId] ":" [ranges] | [measureId] ":!" [range] }
   [measureId] == { [measureCode] | [measureCode] [digits] }
   [measureCode == { "d" | "a" | "t" }
   [ranges] == {[range] | [ranges] { "," | "-" } [range]}
   [range] == [minimumValue] { "," | "-" } [maximumValue]
   [minimumValue] == [decimalNumber]
   [maximumValue] == [decimalNumber]

</pre>
<br><br>

<a name="aromaticity"><h3>Jmol SMILES and Jmol SMARTS Definition of "aromatic"</h3></a>

<br><br>

The default Jmol SMILES and Jmol SMARTS defines "aromatic" unambiguously and strictly geometrically. However
 you can use the directive /aromaticStrict/ to add to that a 6-electron Hueckel model for specifying aromaticity. 
This discussion relates to the 3D definition. We define "aromatic" here strictly in terms of geometry - a flat ring with trigonal planar geometry for all atoms in the ring. 
No consideration of bond order is used, because for the sorts of models that can be loaded into Jmol, many do not
assume a bonding scheme (PDB, GAUSSIAN, etc.).
<br><br>
<br><br>
    Given a ring of N atoms...
    
<pre>
                  1
                /   \
               2     6 -- 6a
               |     |
         5a -- 5     4
                \   /
                  3  
</pre>
    
    with arbitrary order and up to N substituents...

<ol>
<li>    
    Check to see if all ring atoms have no more than 3 connections.
       Note: An alternative definition might include "and no substituent
       is explicitly double-bonded to its ring atom, as in quinone.
       Here we opt to allow the atoms of quinone to be called "aromatic."
</li><li> Select a cutoff value close to zero. We use 0.01 here (increased to 0.1 for /aromaticStrict/). 
</li><li> Generate a set of normals as follows:
<ol style="list-style-type: lower-alpha;"><li> For each ring atom, construct the normal associated with the plane
          formed by that ring atom and its two nearest ring-atom neighbors.
</li><li> For each ring atom with a substituent, construct a normal 
          associated with the plane formed by its connecting substituent
          atom and the two nearest ring-atom neighbors.
</li><li> If this is the first normal, assign vMean to it. 
</li><li> If this is not the first normal, check vNorm.dot.vMean. If this
          value is less than zero, scale vNorm by -1.
</li><li> Add vNorm to vMean. 
</ol>
</li><li>Calculate the standard deviation of the dot products of the 
       individual vNorms with the normalized vMean. 
</li><li>The ring is deemed flat if this standard deviation is less 
       than the selected cutoff value. 
</li></ol>
       
<br><br>

<br><br>
 -- <a href="mailto:hansonr@stolaf.edu">Bob Hanson</a>  
 <br>updated 8/26/2015: switch to HTML5; added measure option for multiple ranges 
 <br>updated 5/21/2012: added $(select...)
 <br>updated 5/13/2012: added /aromaticStrict/ and /aromaticDouble/ 
 <br>updated 5/13/2012: added [&lt;atomType>] 
 <br>updated 4/10/2012: fix for [$(...)n] and [$(...)min-max]
 <br>original5/19/2010
 <br><br>
</body>
</html>
